﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Media;

using TinyLib.Input;

namespace TinyLib.Audio
{
    public class SoundManager : GameComponent
    {
        #region Sound Properties For Dummies

        //Volume, ranging from 0.0f (silence) to 1.0f (full volume). 1.0f is full volume 
        //Pitch adjustment, ranging from -1.0f (down one octave) to 1.0f (up one octave). 0.0f is unity (normal) pitch.
        //Panning, ranging from -1.0f (full left) to 1.0f (full right). 0.0f is centered.
        //State - Gets the current state (playing, paused, or stopped) of the SoundEffectInstance.
        //IsLooped - Gets a value that indicates whether looping is enabled for the SoundEffectInstance.

        //Play, Pause, Resume, Stop

        #endregion

        //fixa funktioner och liknande för att ändra alla former av ljudproperties

        #region Fields

        // Change MaxSounds to set the maximum number of simultaneous sounds that can be playing.
        private const int MaxSounds = 32; //Ska dock vara unlimited på Windowsburkar...
        private SoundEffectInstance[] playingSounds = new SoundEffectInstance[MaxSounds];
        public SoundEffectInstance[] loopingSounds = new SoundEffectInstance[MaxSounds];
        private SoundEffectInstance[] playingSoundsList = new SoundEffectInstance[MaxSounds];
        public Dictionary<String, SoundEffect> soundEffects = new Dictionary<string, SoundEffect>();
        public Dictionary<String, SoundEffectInstance> soundEffectszz = new Dictionary<string, SoundEffectInstance>();
        private float fSoundVolume = 0;
        public bool pauseLooping = false;

        #endregion

        #region Properties
        #endregion

        #region Inits

        public SoundManager(Game game)
            : base(game)
        {
        }

        public override void Initialize()
        {
            IniFile configFile = new IniFile("textRef\\Values.ini");
            configFile.Parse();

            //iSoundVolume = int.Parse(configFile.GetValue("Music", "MusicVolume"));
            fSoundVolume = 1.0f;
        }

        public void LoadSound(string soundName)
        {
            //LoadSound("Audio//SFX//" + soundName);
            LoadSound(soundName, "Audio//SFX//" + soundName);

        }

        public void LoadSound(string soundName, string soundPath)
        {
            if (soundEffects.ContainsKey(soundName))
            {
                throw new InvalidOperationException(string.Format("Sound '{0}' has already been loaded", soundName));
            }

            soundEffects.Add(soundName, Game.Content.Load<SoundEffect>(soundPath));
        }

        #endregion

        #region Set Sound Properties

        public void setPitch(string soundName, float pitch)
        {
            //Pitch adjustment, ranging from -1.0f (down one octave) to 1.0f (up one octave). 0.0f is unity (normal) pitch.

            //soundEffects[soundName].

            // SoundEffect kiss = new SoundEffect();
            // kiss.Name = "kiss";

            //SoundEffectInstance bajs = new SoundEffectInstance();
            //bajs.Pitch = 1.0f;
        }

        public void setVolume(string soundName, float volume)
        {
            //Volume, ranging from 0.0f (silence) to 1.0f (full volume). 1.0f is full volume 

        }

        public void setPan(string soundName, float pan)
        {
            //Panning, ranging from -1.0f (full left) to 1.0f (full right). 0.0f is centered.

        }


        #endregion

        #region Play Sound

        public void PlaySound(string soundName)
        {
            if (fSoundVolume > 0.05f)
            {
                PlaySound(soundName, fSoundVolume, 0.0f, 0.0f);
            }
        }

        public void PlaySound(string soundName, float pitch)
        {
            if (fSoundVolume > 0.05f)
            {
                PlaySound(soundName, fSoundVolume, pitch, 0.0f);
            }
        }

        public void PlaySound(string soundName, float volume, float pitch, float pan)
        {
            SoundEffect sound;

            if (!soundEffects.TryGetValue(soundName, out sound))
            {
                throw new ArgumentException(string.Format("Sound '{0}' not found", soundName));
            }

            int index = GetAvailableSoundIndex();

            if (index != -1)
            {
                playingSounds[index] = sound.CreateInstance();
                playingSounds[index].Volume = volume;
                playingSounds[index].Pitch = pitch;
                playingSounds[index].Pan = pan;
                playingSounds[index].Play();

                if (!Enabled)
                {
                    playingSounds[index].Pause();
                }
            }
        }

        #endregion

        #region Loop Sound

        public void LoopSound(string soundName)
        {
            if (fSoundVolume > 0.025)
            {
                LoopSound(soundName, fSoundVolume, 0.0f, 0.0f);
            }
        }

        public void LoopSound(string soundName, float volume)
        {
            if (volume > 0.025)
            {
                LoopSound(soundName, volume, 0.0f, 0.0f);
            }
        }

        private int GetAvailableLoopIndex()
        {
            for (int i = 0; i < loopingSounds.Length; ++i)
            {
                if (loopingSounds[i] == null)
                {
                    return i;
                }
            }

            return -1;
        }

        public void LoopSound(string soundName, float volume, float pitch, float pan)
        {
            SoundEffect sound;

            if (!soundEffects.TryGetValue(soundName, out sound))
            {
                throw new ArgumentException(string.Format("Sound '{0}' not found", soundName));
            }

            int index = GetAvailableLoopIndex();

            if (index != -1)
            {
                loopingSounds[index] = sound.CreateInstance();
                loopingSounds[index].Volume = volume;
                loopingSounds[index].Pitch = pitch;
                loopingSounds[index].Pan = pan;
                loopingSounds[index].Play();

                if (!Enabled || pauseLooping)
                {
                    loopingSounds[index].Pause();
                }
                if (pauseLooping)
                {
                    loopingSounds[index].Pause();
                }
            }
        }

        #endregion

        #region Effects

        public void SoundFade()
        {
        }

        public void SoundTuneUp()
        {
        }

        #endregion

        #region Misc Functions

        public override void Update(GameTime gameTime)
        {
            for (int i = 0; i < playingSounds.Length; ++i)
            {
                if (playingSounds[i] != null && playingSounds[i].State == SoundState.Stopped)
                {
                    playingSounds[i].Dispose();
                    playingSounds[i] = null;
                }
            }

            for (int i = 0; i < loopingSounds.Length; ++i)
            {
                if (loopingSounds[i] != null && loopingSounds[i].State == SoundState.Stopped)
                {
                    loopingSounds[i].Play();
                }
            }

            base.Update(gameTime);
        }

        private int GetAvailableSoundIndex()
        {
            for (int i = 0; i < playingSounds.Length; ++i)
            {
                if (playingSounds[i] == null)
                {
                    return i;
                }
            }

            return -1;
        }

        // Pauses all music and sound if disabled, resumes if enabled.
        protected override void OnEnabledChanged(object sender, EventArgs args)
        {
            if (Enabled)
            {
                for (int i = 0; i < playingSounds.Length; ++i)
                {
                    if (playingSounds[i] != null && playingSounds[i].State == SoundState.Paused)
                    {
                        playingSounds[i].Resume();
                    }
                }

            }
            else
            {
                for (int i = 0; i < playingSounds.Length; ++i)
                {
                    if (playingSounds[i] != null && playingSounds[i].State == SoundState.Playing)
                    {
                        playingSounds[i].Pause();
                    }
                }

                MediaPlayer.Pause();
            }

            base.OnEnabledChanged(sender, args);
        }

        #endregion
    }
}
